
"""
Base64 is a binary-to-text encoding scheme to represent binary data in ASCII.

Though Python provides a Base64 class, the plug-in uses a private \
implemention to support the format converter.
"""

__version__ = "1.3.1"
__aof__ = ('Base64 Decoder', 'UUE')
__extension__ = (('Base64 Files', ('*.uue',)),)

_IGNORE_S_RECORD = 'Ignore S-Record Format'

__configs__ = (
    {'name': _IGNORE_S_RECORD,
     'attr': 'bool',
     'default': False},
)

_BASE64CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
               "abcdefghijklmnopqrstuvwxyz" \
               "0123456789+/="

_RERVESEDTABLE = dict()
for k, c in enumerate(_BASE64CHARS):
    _RERVESEDTABLE[c] = k


class _DecodeBase64:
    def Execute(self, source, output, notify, **kws):
        start = kws.get('start', 0)
        length = kws.get('length', len(source)) - start
        if length < 0:
            length = 0

        source.seek(start)

        ret = True
        srecord = True
        ignored = False
        if '_i' in kws:
            configs = kws['_i'].configs()
            ignored = configs.get(_IGNORE_S_RECORD, ignored)

        while ret and length > 0:
            li = source.readline()
            length -= len(li)

            li = li.strip()
            if len(li) % 4 != 0:
                # every line can be mod by 4
                ret = False
                break
            elif len(li) > 0 and li[0] != 'S':
                srecord = False

            for k in range(0, len(li), 4):
                val, z = (0, 0)
                for o in range(0, 4):
                    c = li[k + o]
                    v = _RERVESEDTABLE.get(c, -1)
                    if v == -1:
                        ret = False
                        break

                    if c != '=':
                        z += 1
                    val = val * 64 + v

                output.write(chr((val >> 16) & 0xff))
                if z > 2:
                    output.write(chr((val >> 8) & 0xff))
                if z > 3:
                    output.write(chr(val & 0xff))

        return (not srecord or ignored) and ret


def cvtService():
    return _DecodeBase64
